package com.shujia.day15;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Demo01BreadProduct {
    public static void main(String[] args) {
        // TODO 面包柜 可以使用集合表示 => BreadList
        ArrayList<Bread> list = new ArrayList<>();

        // 启动生产者线程
        Producer producer = new Producer("面包师傅", list);
        producer.start();

        Consumer consumer = new Consumer(5, list);
        new Thread(consumer, "李国涛").start();
        new Thread(consumer, "李玉龙").start();

    }

    static class Bread {
        private String type;

        public Bread(String type) {
            this.type = type;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        @Override
        public String toString() {
            return "Bread{" +
                    "type='" + type + '\'' +
                    '}';
        }
    }

    /*
        TODO 生产者
            面包生产者 线程
     */
    static class Producer extends Thread {
        List<Bread> breadList;
        String[] types;
        Random random;

        public Producer(String name, List<Bread> breadList) {
            super(name);
            this.breadList = breadList;
            types = new String[]{"蓝莓", "原味", "肉松"};
            random = new Random();
        }

        @Override
        public void run() {
            /*
                面包生产者每 3秒 生产一个面包 => 对于当前线程 每次循环需要睡眠 3秒
                柜子中由生产者生产了一些各种口味的面包
             */
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                // TODO 注意：当生产者在调用 breadList进行判断时，要求 其他消费者线程不能获取到 breadList
                synchronized (breadList) {
                    if (breadList.size() > 10) {
                        // 当面包柜中的面包超过10个 那么停止生产 => 对当前线程进行等待阻塞
                        try {
                            // wait的使用必须是有 synchronized() 修饰  =>
                            System.out.println("面包柜中面包数量超过了10个，那么面包师傅休息一段时间");
                            breadList.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        Bread bread = new Bread(types[random.nextInt(3)]);
                        System.out.println(this.getName() + "生产了一个" + bread.getType() + "口味的面包");
                        breadList.add(bread);
                        System.out.println("面包柜中的面包数:" + breadList);

                        // TODO 当面包柜中有面包时，需要告诉消费者消费面包
                        breadList.notifyAll();
                    }
                }


            }

        }
    }

    /*
        TODO 消费者
     */
    static class Consumer implements Runnable {
        int second;
        List<Bread> breadList;

        public Consumer(int second, List<Bread> breadList) {
            this.second = second;
            this.breadList = breadList;
        }

        @Override
        public void run() {
            /*
                两个面包消费者每 5秒吃一个面包
                    那么当面包柜里面没有面包时，消费者开始等待 唤醒生产者开始生产
             */
            while (true) {
                // 当breadList中的面包数量大于0 时消费  如果小于零 怎么办
                Bread eatBread = null;
                synchronized (breadList) {
                    if (breadList.size() > 0) {
                        eatBread = breadList.remove(0);
                    } else {
                        // TODO 当面包柜中没有面包时 告诉其他线程 并进行等待阻塞，当生产者生产面包后，可以唤醒消费者
                        breadList.notifyAll();
                        try {
                            breadList.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
                // TODO 当消费者拿到一个面包后，就离开柜台，独自吃了N秒钟时间 吃完后，再打印
                if (eatBread !=null) {
                    try {
                        Thread.sleep(second * 1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("当前消费者:" + Thread.currentThread().getName() + "吃了一个" + eatBread.getType() + "口味的面包");
                }

                // TODO 为了防止一个消费者一直站在柜台前，独自消费，那么当消费完成后，可以暂停一段时间
//                try {
//                    Thread.sleep(200);
//                } catch (InterruptedException e) {
//                    throw new RuntimeException(e);
//                }
            }
        }
    }
}
